import { updateFragementComponent, updateFunctionComponent, updateHostComponent } from "./reactFiberReconciler"
import { isFn, isStr } from "./utils/utils"


let wipRoot: IFiber | any = null
let nextFiberOfWork: IFiber | null = null


// 遍历jsx，生成fiber
export function scheduleUpdateOnFiber(fiber: IFiber) {
    wipRoot = fiber
    nextFiberOfWork = fiber
}

function performUnitOfWork(wip: any):IFiber | any {
    // 1. 更新wip
    const { type } = wip
    if(isStr(type)) {
        updateHostComponent(wip)
    }else if(isFn(type)) {
        updateFunctionComponent(wip)
    }else {
        updateFragementComponent(wip)
    }

    // 2. 返回下一个要更新的任务 DFS
    if(wip.child) {
        return wip.child
    }

    let next = wip
    while(next) {
        if(next.sibling) {
            return next.sibling
        }
        next = next.return
    }
    return null
}

function wookLoop(idleDeadline: any) {
    while(nextFiberOfWork && idleDeadline.timeRemaining() > 0) {
        nextFiberOfWork = performUnitOfWork(nextFiberOfWork)
    }

    if(nextFiberOfWork === null && wipRoot) {
        commitRoot()
    }
}
requestIdleCallback(wookLoop)

function commitRoot() {
    commitWorker(wipRoot.child)
    wipRoot = null
}

function commitWorker(wip: IFiber) {
    if(!wip) {
        return
    }

    const { stateNode } = wip
    let parentNode = getParentNode(wip.return)
    if(stateNode) {
        parentNode.appendChild(stateNode)
    }
    commitWorker(wip.child)
    commitWorker(wip.sibling)
}

function getParentNode(fiber: IFiber) {
    while(fiber) {
        if(fiber.stateNode) {
            return fiber.stateNode
        }
        fiber = fiber.return
    }
}